// -*- c++ -*-
/**************************************************************/
/*  This file is licensed from, and is a trade secret of:     */
/*                                                            */
/*    Mercury Computer Systems, Incorporated                  */
/*    199 Riverneck Road                                      */
/*    Chelmsford, Massachusetts 01824-2820                    */
/*    United States of America                                */
/*    Telephone + 1 978 256-1300                              */
/*                                                            */
/*  Refer to your Software License Agreement for provisions   */
/*  on use, duplication, or disclosure.                       */
/*  US. Government users and prime contractors are also       */
/*  governed by the following Data Rights Notice:             */
/*  Use, duplication or disclosure by the US. Government is   */
/*  subject to the provisions set forth in FAR 52.227-14 for  */
/*  restricted rights or other agency data rights provisions  */
/*  on commercial software and documentation, as applicable.  */
/*                                                            */
/*  This file: (a) was developed at private expense, and no   */
/*  part was developed with government funds, (b) is a        */
/*  trade secret of Mercury Computer Systems, Inc. for the    */
/*  purposes of the Freedom of Information Act, (c) is        */
/*  "commercial computer software" subject to limited         */
/*  utilization as provided in the above noted Software       */
/*  License Agreement and (d) is in all respects data         */
/*  belonging exclusively to Mercury Computer Systems, Inc..  */
/*                                                            */
/**************************************************************/

/******************************************************************/
/* Copyright (c) 1999-2003, Mercury Computer Systems, Inc.,       */
/* Chelmsford MA.,and all third party embedded software sources.  */
/* All rights reserved under the Copyright laws of US. and        */
/* international treaties.                                        */
/*                                                                */
/* Patent Pending                                                 */
/******************************************************************/


//$COPYRIGHT_END


#ifndef BASE_ASSEMBLY_CONTROLLER_H__
#define BASE_ASSEMBLY_CONTROLLER_H__

#include <vector>
#include "mc_error.h"
#include "CF__Resource_impl.h"
#include "CF__Port_impl.h"


#ifdef _WIN32
#ifndef BASEAC_EXPORTS
#define BASEAC_EXPORT __declspec(dllimport)
#else 
#define BASEAC_EXPORT __declspec(dllexport)
#endif 
#else //_WIN32
#define BASEAC_EXPORT
#endif // _WIN32

//forward declaration
class BaseAssemblyControllerPort;

/*
 * This is a class that can be a generic assembly controller for a variety 
 * of applications.  The mapping is included for a number of properties
 * for a number of applications.
 */

class BASEAC_EXPORT BaseAssemblyController : public virtual CF__Resource_impl {
public:
  static status Create(BaseAssemblyController *& AssemblyControllerHandle,
		       const char * identifier);
  virtual ~BaseAssemblyController();

  // From CF::Resource::PortSupplier
  virtual CORBA::Object_ptr getPort (const CORBA::Char * name)
    throw (CORBA::SystemException, CF::PortSupplier::UnknownPort);

  // From CF::Resource::PropertySet
  virtual void configure (const CF::Properties& configProperties)
    throw (CORBA::SystemException, CF::PropertySet::InvalidConfiguration,
           CF::PropertySet::PartialConfiguration);
  virtual void query (CF::Properties& configProperties)
    throw (CORBA::SystemException, CF::UnknownProperties);

  // From CF::Resource::LifeCycle
  virtual void initialize ()
    throw (CORBA::SystemException, CF::LifeCycle::InitializeError);

  // From CF::Resource
  virtual void start ()
    throw (CORBA::SystemException, CF::Resource::StartError);
  virtual void stop ()
    throw (CORBA::SystemException, CF::Resource::StopError);

  status addObject (CORBA::Object_ptr object, const CORBA::Char* Id);
  status removeObject (const CORBA::Char* Id);

  // Callback for base classes to set up property mappings between
  // assembly and resources
  void AddPropertyMapping (const char *assembly_property_name, 
			   const char *component_id,
			   const char *component_property_name);

protected:

  void SetPropertyMappingObjectReferences (CF::Resource_ptr res);

  // Internal class used to implement the property mapping.
  class PropertyMapTarget {
  public:
    PropertyMapTarget (const char * component_id, const char * prop_name);
    ~PropertyMapTarget ();

    std::string  m_component_id;
    CF::Resource_ptr   m_res_ref;
    CF::Properties     m_cf_properties;
    CF::DataType       *m_cf_property;
  };

  // Forward declaration.
  class ComponentPropertyQueue;

  // Internal class used to implement the property mapping.
  class PropertyMapping {
  public:
    PropertyMapping (const char * assembly_property_name, 
		     const char * component_id,
		     const char * component_prop_name);
    ~PropertyMapping ();

    bool PropertyTypeMatch (const CF::DataType & cf_prop);
    void SetPropValues (const CF::DataType & cf_prop);
    void GetPropValue (CF::DataType & cf_prop, unsigned long index=0);
    void AddPropertyTarget (const char * component_id,
			    const char * component_prop_name);

  public:
    std::string m_assembly_propname;

  private:
    bool m_initial_set;
    std::vector<PropertyMapTarget *> m_targets;
    friend class BaseAssemblyController;
    friend class ComponentPropertyQueue;
  };


  /*
   * The ComponentPropertyQueue is used by the BaseAssemblyController Object
   * It allows the BaseAssemblyController, during configure(), to queue up
   * components and set all the properties for a component at the same time.
   * Previously it did them one at a time and 
   */

  class ComponentPropertyQueue {
  public:
    // Constructor
    ComponentPropertyQueue () {}
    ~ComponentPropertyQueue ();

    // Queues up the properties via components
    void QueuePropValues (PropertyMapping & prop_map, const CF::DataType & cfgProp);  
    // Configure each of the components in the queues
    void ConfigureComponentProps ();

  private:
    int GetPropertyCompIndex (const char *);

    struct component_properties {
      std::string m_component_id;
      CF::Resource_ptr m_res_ref;
      CF::Properties m_comp_cf_properties;
    };

    std::vector<struct component_properties *> m_component_props;
    std::map<std::string, int> m_component_index_mappings;
  };

  BaseAssemblyController ();
  BaseAssemblyController (const char * identifier);

  BaseAssemblyControllerPort * m_myPort_impl; // For connecting to components
  CF::Port_var m_myPort_var;

  // Keep the Resources controlled by this Assembly controller in a list.
  struct ResourceListNode {
    CORBA::Char * _resName;
    CORBA::Char * _connId;
    CF::Resource_ptr _resRef;
    ResourceListNode * _next;
  };

  ResourceListNode * m_resHead;

  std::vector<PropertyMapping *> m_prop_mappings;
};

class BASEAC_EXPORT BaseAssemblyControllerPort : public CF__Port_impl {
public:
  BaseAssemblyControllerPort (BaseAssemblyController * parentAssemblyController);
  ~BaseAssemblyControllerPort ();

  void connectPort (CORBA::Object_ptr connection,
		    const CORBA::Char * connectionId)
    throw (CORBA::SystemException,
	   CF::Port::InvalidPort, 
           CF::Port::OccupiedPort);

  void disconnectPort (const CORBA::Char * connectionId)
    throw (CORBA::SystemException, CF::Port::InvalidPort);

protected:
  BaseAssemblyController * m_myParentAssemblyController;
};

#endif // BASE_ASSEMBLY_CONTROLLER_H__
